unit cp_shapes;

{$IFDEF FPC}
  {$mode delphi}
{$ENDIF}

interface

uses
  zglChipmunk;

  procedure RuleBall();
  procedure AddBar();
  procedure AddBall(x, y: Single);
  procedure DelBall(body: PcpBody);
  procedure PinUp();
  procedure PinDown();

  procedure Draw();

implementation

uses
  zglHeader, g_vars, c_list, utils;

type
  TballData = class
    r: PDouble;  //Радиус
    Scale: Single;
    Color: Cardinal;
    Tex, Tex1: zglPTexture;
    Eye: zglPTexture;
    EyeV: array [0..1] of cpVect;
  end;

var
  bodys: TList;
  joint: PcpConstraint; //Единение для перетаскивания объекта мышью


procedure rBallPos( body : PcpBody; dt : cpFloat ); cdecl;
begin
  body.p.x := mouse_X;
  body.p.y := mouse_Y;
end;

procedure RuleBall();
begin
  mBall := cpBodyNew(INFINITY, INFINITY);
  mBall.p := cpv(0, 0);
//  mBall.position_func := rBallPos;
end;

procedure AddBar();
const
  mass = 10;
  mass1 = 10;
  a: cpVect = (x: 150; y: 0);
  b: cpVect = (x:-150; y: 0);
var
  pos: cpVect;
  wbody: PcpBody;
  body: PcpBody;
  aa, bb: cpVect;
  shape: PcpShape;
  cons: PcpConstraint;
begin
  pos.x := SCREEN_WIDTH/2;
  pos.y := SCREEN_HEIGHT/2-220;
  wbody := cpSpaceAddBody(Space, cpBodyNew(mass, cpMomentForSegment(mass, a, b)));
  wbody.p := pos;
  shape := cpSpaceAddShape(Space, cpSegmentShapeNew(wbody, a, b, 5));
  shape.e := 0;
  shape.u := 0.7;

  //Шпилим бар к стене
  cons := cpSpaceAddConstraint(space, cpPivotJointNew(wbody, stBody, pos));
  cons.biasCoef := 0;

  //-------------------Делаем весы-----

  aa := cpvmult(a, 0.5);
  bb := cpvmult(b, 0.5);

  //левая часть
  body := cpSpaceAddBody(Space, cpBodyNew(mass1, cpMomentForSegment(mass1, aa, bb)));
  body.p := cpv(SCREEN_WIDTH/2 - 150, SCREEN_HEIGHT-100);
  shape := cpSpaceAddShape(Space, cpSegmentShapeNew(body, aa, bb, 5));
  shape.e := 0;
  shape.u := 0.7;
  cpSpaceAddConstraint(Space, cpPinJointNew(wbody, body, b, aa));
  cpSpaceAddConstraint(Space, cpPinJointNew(wbody, body, b, bb));

  //Правая часть
  body := cpSpaceAddBody(Space, cpBodyNew(mass1, cpMomentForSegment(mass1, aa, bb)));
  body.p := cpv(SCREEN_WIDTH/2 + 150, SCREEN_HEIGHT-100);
  shape := cpSpaceAddShape(Space, cpSegmentShapeNew(body, aa, bb, 5));
  shape.e := 0;
  shape.u := 0.7;
  cpSpaceAddConstraint(Space, cpPinJointNew(wbody, body, a, aa));
  cpSpaceAddConstraint(Space, cpPinJointNew(wbody, body, a, bb));
end;

procedure AddBall(x, y: Single);
const
  stR = 15;
  stMass = 0.1;
  e = 0.1;
  u = 0.7;
var
  r: Single;
  mass: Single;
  bBody: PcpBody;
  bShape: PcpCircleShape;
  bd: TballData;
  hsl: THSVColor;
begin
  r := Random(20) + stR;
  mass := ((r - stR) + 1) / 10;
  bBody   := cpBodyNew(mass, cpMomentForCircle(mass, 0, r, cpvzero));
  bBody.p := cpv(x, y);
  cpSpaceAddBody(space, bBody);
  bodys.Add(bBody);

  bd := TballData.Create();
  hsl.H := Random(255);
  hsl.S := Random(128) + 128;
  hsl.V := 255;
  bd.Color := HSVtoRGB(hsl).rgba;
  bd.Tex  := resMan.LoadTex('body.png');
  bd.Tex1 := resMan.LoadTex('body_shyne.png');
  bd.Eye := resMan.LoadTex('eye_' + u_IntToStr(Random(9) + 1) + '.png');
  bd.Scale := r * 2 / bd.Tex.Width;
  bBody.data := bd;

  bShape := PcpCircleShape(cpCircleShapeNew(bBody, r, cpvzero));
  bShape.shape.e := e;
  bShape.shape.u := u;
  bd.r := @bShape.r;
  cpSpaceAddShape(space, @bShape.shape);
end;

procedure DelBall(body: PcpBody);
var
  i: Integer;
begin
  for i := 0 to bodys.Count - 1 do
  begin
    if PcpBody(bodys.Items[i]) = body then
    begin
      TballData(body.data).Free;
      bodys.Del(i);
      Break;
    end;
  end;
end;

procedure PinUp();
var
  b: PcpBody;
  sh: PcpCircleShape;
  point: cpVect;
begin
  point := cpv(mouse_X, mouse_Y);

  sh := PcpCircleShape(cpSpacePointQueryFirst(Space, point, 2, 0));
  if Assigned(sh) then
  begin
//    sh.r := sh.r + 1;
    b := sh.shape.body;
    joint := cpPivotJointNew2(mBall, b, cpvzero, cpBodyWorld2Local(b, point));
//    joint := cpSlideJointNew(mBall, b, cpvzero, cpBodyWorld2Local(b, point), 0, 100);
    joint.maxForce := 50000;
    joint.biasCoef := 0.15;
    cpSpaceAddConstraint(Space, joint);
  end;
end;

procedure PinDown();
begin
  if Assigned(joint) then
  begin
    cpSpaceRemoveConstraint(Space, joint);
    cpConstraintFree(joint);
    joint := Nil;
  end;
end;

procedure Draw();
var
  i: Integer;
  b: PcpBody;
  bd: TballData;
  r: Single;
begin
  for i := 0 to bodys.Count - 1 do
  begin
    b := PcpBody(bodys.Items[i]);
    bd := TballData(b.data);
    r := bd.r^;
    fx2d_SetColor(bd.Color);
    ssprite2d_Draw(bd.Tex,
      b.p.x - r,
      b.p.y - r,
      r * 2,
      r * 2,
      0, $FF,
      FX_COLOR or FX_BLEND);


    if DrawFace then
      ssprite2d_Draw(bd.Eye,
        b.p.x - r,
        b.p.y - r,
        r * 2,
        r * 2,
        b.a * rad2deg);

    {//Правй глаз
    ssprite2d_Draw(EyeBall,
        b.p.x + (EYE_DIST * cos(b.a - EYE_DEG * deg2rad) - EyeBall.Width / 2) * bd.Scale ,
        b.p.y + (EYE_DIST * sin(b.a - EYE_DEG * deg2rad) - EyeBall.Width / 2) * bd.Scale,
        EyeBall.Width * bd.Scale,
        EyeBall.Height * bd.Scale,
        b.a * rad2deg);
    //Левый глаз
    ssprite2d_Draw(EyeBall,
        b.p.x + (EYE_DIST * cos(b.a - (180 - EYE_DEG) * deg2rad) - EyeBall.Width / 2) * bd.Scale ,
        b.p.y + (EYE_DIST * sin(b.a - (180 - EYE_DEG) * deg2rad) - EyeBall.Width / 2) * bd.Scale,
        EyeBall.Width * bd.Scale,
        EyeBall.Height * bd.Scale,
        b.a * rad2deg);}

    ssprite2d_Draw(bd.Tex1,
      b.p.x - r,
      b.p.y - r,
      r * 2,
      r * 2,
      0);
  end;
end;

initialization
  bodys := TList.Create;

finalization
  bodys.Free;

end.

